/*
 * main.cpp
 *
 *  Created on: 06/10/2011
 *      Author: mario
 */

#include "src/gui/GraphicUserInterface.h"
#include "src/control/ElectionManager.h"
#include "src/loader/CsvLoader.h"
#include "src/exception/CsvFormatException.h"
#include "src/hash/exceptions/ExceptionExists.h"
#include <iostream>
#include "src/log/Logger.h"
#include "src/tree/BPlusTree.h"
#include "src/tree/Record.h"
#include "src/Candidato.h"
#include "src/Votante.h"
#include "src/Cargo.h"
#include "src/Lista.h"
#include "util/NodoEleccion.h"

#include "src/control/CandidatoDao.h"
#include "src/control/ListaDao.h"

using namespace std;
using std::string;

void testLoadFromCsv() {
	Logger logger;
	CsvLoader* l = CsvLoader::getInstance();
	string path;
	getline(cin, path);
	try {
		l->loadCsv('a',path);
	} catch (CustomException e) {
		logger.createEntryLog(e.what(), e.getType());
	}

}

void testVotanteLogin() {
	Distrito* distrito = Distrito::create(1,"Buenos Aires");

	Votante* votante = Votante::create(123,"Lalal","lalalaa","123",distrito,NULL);
    stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
    votante->toData(&ss);

    tree::Record* record = new tree::Record();
	record->edit(votante->getDni(), &ss);

	tree::BPlusTree* tree = new tree::BPlusTree(VOTANTES, BLOCKSIZE);
    tree->insert(record);

    ElectionManager* manager = new ElectionManager();
    int result = manager->login(123,"123");
    cout << "RESULTADO LOGIN: " << result << endl;
}

void testVotantesAddedToTree() {
	CsvLoader* l = CsvLoader::getInstance();
	l->loadCsv('a',"resources/votantes");

	cout << "----------------ARBOL----------------" << endl;

	tree::BPlusTree* tree = new tree::BPlusTree(VOTANTES, BLOCKSIZE);
	tree::Record* record = tree->iterate();
	while(record != NULL){
		stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
		ss.write(record->getData(), record->getDataSize());
		Votante* votante = Votante::toObject(&ss);

		cout << "DNI: " <<  votante->getDni() << endl;
		cout << "Nombre: " <<  votante->getNombre() << endl;
		cout << "Apellido: " <<  votante->getApellido() << endl;
		cout << "Password: " <<  votante->getPassword() << endl;
		cout << "ID distrito: " <<  votante->getDistrito()->getId() << endl;

		free (votante->getDistrito());
		record = tree->iterate();
	}
	cout << "----------------ITERATED----------------" << endl;
}

void testCandidatosAddedToTree() {
	CsvLoader* l = CsvLoader::getInstance();
	l->loadCsv('a',"resources/candidatos");

	cout << "----------------ARBOL----------------" << endl;

	tree::BPlusTree* tree = new tree::BPlusTree(CANDIDATOS, BLOCKSIZE);
	tree::Record* record = tree->iterate();
	while(record != NULL){
		stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
		ss.write(record->getData(), record->getDataSize());
		Candidato* candidato = Candidato::toObject(&ss);

		cout << "id: " <<  candidato->getId() << endl;
		cout << "DNI: " <<  candidato->getVotante()->getDni() << endl;
		cout << "id cargo: " <<  candidato->getCargo()->getId() << endl;
		cout << "id lista: " <<  candidato->getLista()->getId() << endl;

		free (candidato->getVotante());
		free (candidato->getCargo());
		free (candidato->getLista());
		record = tree->iterate();
	}
}

void testDistritosAddedToTree() {
	CsvLoader* l = CsvLoader::getInstance();
	l->loadCsv('a', "resources/distritos");

	cout << "----------------ARBOL----------------" << endl;

	tree::BPlusTree* tree = new tree::BPlusTree(DISTRITOS, BLOCKSIZE);
//	tree->dumpToXML("distr");
		for(int i=0; i <9; i++){
		tree::Record* record = tree->iterate();
		stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
		ss.write(record->getData(), record->getDataSize());
		Distrito* distrito = Distrito::toObject(&ss);

		cout << "id: " <<  distrito->getId() << endl;
		cout << "DNI: " <<  distrito->getNombre() << endl;

		free (distrito);
	}
}


void addCandidato(tree::BPlusTree* tree, int dni, int idCargo, int idLista, int idCandidato){
	Votante* votante = new Votante();
	votante->setDni(dni);

	Cargo* cargo = new Cargo();
	cargo->setId(idCargo);

	Lista* lista = new Lista();
	lista->setId(idLista);

	int id = idCandidato;

	Candidato* candidato = Candidato::create(id, votante, lista, cargo);

	stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
	candidato->toData(&ss);

	tree::Record* record = new tree::Record();
	record->edit(candidato->getId(), &ss);

	int result = tree->insert(record);

	if(result == EXIT_SUCCESS) {
		cout << "Record " << record->getKey() << " has been inserted." << endl;
	} else if(result == DUPLICATED){
		cout << "Record " << record->getKey() << " already exists. Operation failed." << endl;
	} else {
		cout << "Oversized record " << record->getKey() << ". Operation failed." << endl;
	}

}

void findCandidato(int idCandidato){
	tree::Record* record = new tree::Record();
	record->setKey(idCandidato);

	string fileName = "candidatos";
	tree::BPlusTree* tree = new tree::BPlusTree(fileName, 256);

	record = tree->find(record);

	stringstream sss(ios_base::in| ios_base::out| ios_base::binary);
	sss.write(record->getData(), record->getDataSize());

	Candidato* candidato = Candidato::toObject(&sss);

	cout << "id: " <<  candidato->getId() << endl;
	cout << "dni votante: " <<  candidato->getVotante()->getDni() << endl;
	cout << "id lista: " <<  candidato->getLista()->getId() << endl;
	cout << "id cargo: " <<  candidato->getCargo()->getId() << endl;

	free (candidato->getVotante());
	free (candidato->getLista());
	free (candidato->getCargo());
	free (candidato);

	free (tree);
}

void iterate(){
	string fileName = "candidatos";
	tree::BPlusTree* tree = new tree::BPlusTree(fileName, 256);

	for(int i=0; i <20; i++){
		tree::Record* record = tree->iterate();
		stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
		ss.write(record->getData(), record->getDataSize());

		Candidato* candidato = Candidato::toObject(&ss);

		cout << "id: " <<  candidato->getId() << endl;
		cout << "dni votante: " <<  candidato->getVotante()->getDni() << endl;
		cout << "id lista: " <<  candidato->getLista()->getId() << endl;
		cout << "id cargo: " <<  candidato->getCargo()->getId() << endl;

		free (candidato->getVotante());
		free (candidato->getLista());
		free (candidato->getCargo());
		free (candidato);
	}

}


void testLoadSaveToTree(){

	string fileName = "candidatos";
	tree::BPlusTree* tree = new tree::BPlusTree(fileName, BLOCKSIZE);

	addCandidato(tree, 18865845, 34, 45, 57);
	addCandidato(tree, 18855847, 35, 46, 56);
	addCandidato(tree, 18565845, 36, 47, 55);
	addCandidato(tree, 18866845, 37, 48, 54);
//
	addCandidato(tree,15865845, 34, 45, 67);
	addCandidato(tree,15855847, 35, 46, 66);
	addCandidato(tree,15565845, 36, 47, 65);
	addCandidato(tree,15866845, 37, 48, 64);
////
	addCandidato(tree,16865845, 34, 45, 77);
	addCandidato(tree,16855847, 35, 46, 76);
	addCandidato(tree,16565845, 36, 47, 75);
	addCandidato(tree,16866845, 37, 48, 74);
//
	addCandidato(tree, 17865845, 34, 45, 87);
	addCandidato(tree, 17855847, 35, 46, 86);
	addCandidato(tree, 17565845, 36, 47, 85);
	addCandidato(tree, 17866845, 37, 48, 84);

//	tree->dumpToXML("candidatoss.xml");

//
//	findCandidato(67);

	iterate();

}



void testDistrito(){
//	tree::BPlusTree * tree1= new tree::BPlusTree(DISTRITOS,BLOCKSIZE);
//
//	stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
//	Distrito* distrito1 = Distrito::create(3,"Escobarrrr");
//	cout << "id: " << distrito1->getId() << " nombre: " << distrito1->getNombre() << "\n";
//	distrito1->toData(&ss);
//	tree::Record* record1 = new tree::Record();
//	record1->edit(distrito1->getId(), &ss);
//	tree1->modify(record1);
//	free(tree1);
//	free(distrito1);

//	tree::BPlusTree * treeee= new tree::BPlusTree(DISTRITOS,BLOCKSIZE);
//	int result = treeee->remove(new tree::Record(1));
//
//	if(result== EXIT_FAILURE) {
//		cout << "Not such record " << 1 << ". Operation failed." << endl;
//	} else {
//		cout << "Record " << 1 << " has been removed." << endl;
//	}

	tree::BPlusTree * tree= new tree::BPlusTree(DISTRITOS,BLOCKSIZE);
	tree->dumpToXML("distre");


	tree::Record* record = tree->iterate();
	while(record != NULL){
		stringstream ss(ios_base::in| ios_base::out| ios_base::binary);
		ss.write(record->getData(), record->getDataSize());
		Distrito* distrito = Distrito::toObject(&ss);

		cout << "id: " <<  distrito->getId() << endl;
		cout << "name: " <<  distrito->getNombre() << endl;


		free (distrito);
		record = tree->iterate();
	}

	free(tree);



}

void loadEntities() {
	CsvLoader* l = CsvLoader::getInstance();
	l->loadCsv('a',"resources/votantes");
	l->loadCsv('a',"resources/cargos");
	l->loadCsv('a',"resources/candidatos");
	l->loadCsv('a',"resources/listas");
	l->loadCsv('a',"resources/distritos");
	l->loadCsv('a',"resources/elecciones");
}

int getRandomOption(int from, int to){
	srand((unsigned)time(0));
	return from + (rand()%(to+1));
}

int main(int argc, char **argv) {

	GraphicUserInterface* gui = new GraphicUserInterface();
	gui->menu();

	delete gui;

	return 0;
}
